package net.muhu.interfaces;

import static net.muhu.util.MuhuDataFactory.createMusiverse;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

import java.io.File;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import net.muhu.domain.Musiverse;
import net.muhu.domain.ObjectFactory;
import net.muhu.domain.OnlineState;
import net.muhu.domain.Planet;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * XML marshaling test case
 * 
 * @author dagyno
 * 
 */
public class JaxbTestCase {

	private static final String MUSIVERSE_ID = "musiverse";

	private static URL exampleXmlFile;

	private static JAXBContext jaxbContext;

	@BeforeClass
	public static void staticSetup() throws JAXBException {
		jaxbContext = JAXBContext.newInstance(Musiverse.class);
	}

	@Before
	public void setUp() {
		exampleXmlFile = this.getClass().getResource("/MusicHunters.xml");
	}

	@SuppressWarnings("unchecked")
	@Test
	public void checkContextNamespace() throws Exception {
		assertThat(jaxbContext.toString(), allOf( //
				containsString("java.lang.String"), //
				containsString("net.muhu.domain.Musiverse")));
	}

	@Test
	public void readDataFromXml() throws JAXBException, URISyntaxException {
		Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

		JAXBElement<Musiverse> element = unmarshaller.unmarshal(
				new StreamSource(new File(exampleXmlFile.toURI())),
				Musiverse.class);

		Musiverse actual = element.getValue();
		assertEquals(MUSIVERSE_ID, actual.getId());
		assertEquals(OnlineState.ONLINE, actual.getState());
	}

	@Test
	public void writeToString() throws Exception {
		Musiverse musiverse = createMusiverse(MUSIVERSE_ID);
		musiverse.setName("Test Musiverse");
		musiverse.getLocation().add(//
				new Planet()//
						.withId("earth")//
						.withName("Erde"));
		musiverse.setState(OnlineState.ONLINE);

		JAXBElement<Musiverse> musiverseElement = new ObjectFactory()
				.createMusiverse(musiverse);

		StringWriter writer = new StringWriter();
		Marshaller marshaller = jaxbContext.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		marshaller.marshal(musiverseElement, writer);

		String actual = writer.toString();
		assertThat(actual, containsString("<id>" + MUSIVERSE_ID + "</id>"));
	}
}
